/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mrroman.linksender.filesender;

import com.mrroman.linksender.filesender.sendables.SendableRoot;
import com.mrroman.linksender.filesender.sendables.SendableFileWithMimeResolver;
import com.mrroman.linksender.filesender.sendables.SendableFilter;
import com.mrroman.linksender.filesender.sendables.Sendable;
import com.mrroman.linksender.filesender.sendables.SendableTouple;
import com.mrroman.linksender.*;
import com.mrroman.linksender.filesender.pages.PageUpload;
import com.mrroman.linksender.filesender.server.*;
import java.io.*;
import java.net.Socket;
import java.util.HashMap;
import com.mrroman.linksender.ioc.*;
import com.mrroman.linksender.sender.MessageEvent;
import com.mrroman.linksender.sender.PrivateMessagePoint;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;

@Name("filesender.ServerManager")
public class ServerManager extends Server {

    @Locales
    private ResourceBundle messages;
    @Log
    private Logger logger;
    @In
    private Configuration configuration;
    @In
    private PrivateMessagePoint privateMessagePoint;
    public static String ALL_IP = "*.*.*.*";
    public static String LOCAL_IP = "127.0.0.1";
    private SendableRoot pub, root, local;
    private HashMap<String, SendableRoot> list;

    public ServerManager() {
        super();
    }

    @Init
    public void init() {
        logger = Logger.getLogger(ServerManager.class.getName());
    }

    @Override
    public void setParameters(int port, int poolSize, String homePage, String serverName) {
        super.setParameters(port, poolSize, homePage, serverName);
        root = new SendableRoot(null, "root", null);
        pub = new SendableRoot(root, "pub", null);
        local = new SendableRoot(root, "localhost", null);
        File output_directory = new File(configuration.getOutputDirectory());
        if (output_directory == null || !output_directory.exists() || !output_directory.isDirectory() || !output_directory.canWrite()) {
            logger.log(Level.SEVERE, messages.getString("directory_not_found") + ": " + output_directory);
        } else {
            pub.addSendable(new PageUpload(pub, "upload"));
            this.setMenu("<a href=\"/\">root</a>", "<a href=\"/upload\">upload</a>");
            try {
                this.setOutputDirectory(output_directory.getCanonicalPath());
            } catch (IOException ex) {
            }
        }

        root.addSendable(pub);
        root.addSendable(local);
        list = new HashMap<String, SendableRoot>();
        list.put(ALL_IP, pub);
        list.put(LOCAL_IP, local);
    }

    public SendableRoot getSendableRootForIp(final String userIp) {
        if (ALL_IP.equals(userIp)) {
            return pub;
        } else if (LOCAL_IP.equals(userIp)) {
            return local;
        } else {
            SendableRoot priv = list.get(userIp);
            if (priv == null) {
                priv = new SendableRoot(root, userIp, new SendableFilter() {

                    @Override
                    public boolean isAllowed(Sendable sendable, Object ip, Object user) {
                        return (ip.equals(userIp));
                    }
                });
                list.put(userIp, priv);
            }
            return priv;
        }
    }
    private SendableFilter onlyLocalhost = new SendableFilter() {

        @Override
        public boolean isAllowed(Sendable sendable, Object ip, Object user) {
            return LOCAL_IP.equals(ip);
        }
    };

    public Sendable shareFile(File file, String ip) {
        //Scanner users = new Scanner(ips);
        //while (users.hasNext()) {
        SendableRoot sr = getSendableRootForIp(ip);
        Sendable result = new SendableFileWithMimeResolver(sr, file);
        sr.addSendable(result);
        if (local != sr && pub != sr) {
            SendableRoot forIp = (SendableRoot) local.getChild(ip);
            if (forIp == null) {
                forIp = new SendableRoot(local, ip, onlyLocalhost);
                local.addSendable(forIp);
            }
            forIp.addSendable(new SendableFileWithMimeResolver(forIp, file));
        }
        logger.log(Level.INFO, messages.getString("sharing_file") + " " + file + " (" + ip + ")");
//        /privateMessagePoint.sendEvent(new MessageEvent(MessageEvent.EventType.INFO, "system", messages.getString("sharing_file") + " " + file + " (" + ip + ")"));
        return result;
    }

    @Override
    public Sendable getSendableRoot(Socket socket) {
        String ip = socket.getInetAddress().getHostAddress();
        if (LOCAL_IP.equals(ip)) {
            return new SendableTouple(pub, local);
            //return local;
        }
        SendableRoot slave = list.get(ip);
        return slave == null ? pub : new SendableTouple(pub, slave);
    }

    @Override
    public void run() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException ex) {
        }
        //shareFile(new File("C:/devenv"), ALL_IP); shareFile(new File("d:/progs/"), "131.207.229.223");
        logger.info(messages.getString("http_server_started") + ", port: " + port + ", pool: " + poolSize);
        try {
            super.protectedRun();
        } catch (IOException e) {
            String k = e.getLocalizedMessage() + ", port: " + port + ", pool: " + poolSize;
            logger.log(Level.SEVERE, k);
            privateMessagePoint.systemMessage(MessageEvent.EventType.ERROR, k);
        }
    }

    public void stopServer() {
        super.setStarted(false);
        logger.info(messages.getString("http_server_stopped"));
    }
}

